package cn.net.shuxing.yifu.common.front.controller;

import cn.net.shuxing.yifu.common.bean.*;
import cn.net.shuxing.yifu.common.constant.*;
import cn.net.shuxing.yifu.common.dto.BaseDto;
import cn.net.shuxing.yifu.common.dto.CashDealRecordDto;
import cn.net.shuxing.yifu.common.dto.CodeConst;
import cn.net.shuxing.yifu.common.dto.DealRecordDto;
import cn.net.shuxing.yifu.common.service.*;
import cn.net.shuxing.yifu.common.util.JedisUtil;
import cn.net.shuxing.yifu.common.util.RedisKeyCreator;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import cn.net.shuxing.yifu.common.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import redis.clients.jedis.Jedis;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 交易模块Controller
 */
@RestController
@RequestMapping("/front")
public class DealController extends BaseController {
    @Autowired
    private ShareholderBuyGrantHistoryService shareholderBuyGrantHistoryService;
    @Autowired
    private ShareholderCoinGrantHistoryService shareholderCoinGrantHistoryService;
    @Autowired
    private UserCashHistoryService userCashHistoryService;

    @Autowired
    private MemberWalletService memberWalletService;

    @Autowired
    private CashWalletService cashWalletService;

    @Autowired
    private DealCommonService dealCommonService;

    @Autowired
    private OpenPriceHistoryService openPriceHistoryService;

    @Autowired
    private CoinTypeService coinTypeService;

    @Autowired
    private HangBuyService hangBuyService;

    @Autowired
    private HangSaleService hangSaleService;

    @Autowired
    private DealHistoryService dealHistoryService;

    @Autowired
    private CoinRatioService coinRatioService;

    @Autowired
    private UserDealHistoryService userDealHistoryService;

    @Autowired
    private JedisUtil jedisUtil;

    @Autowired
    private DealParamService dealParamService;

    @Autowired
    private FrontCommonService frontCommonService;

    @Autowired
    private ShortService shortService;

    @Autowired
    private UserCapitalService userCapitalService;

    @Autowired
    private UserService userService;

    @Autowired
    private CoinCommonService coinCommonService;

    @Autowired
    private FrontCommenController frontCommenController;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private UserRealInfoService userRealInfoService;

    @RequestMapping("/deal/hangBuy/publish/verify")
    public BaseDto verifyPublishHangBuy(Integer userId, BigDecimal aliveCoinCount, BigDecimal singlePrice, Integer coinTypeId) {
        BaseDto capitalPasswordRequired = frontCommenController.isCapitalPasswordRequired(userId);
        if (capitalPasswordRequired.isError())
            return capitalPasswordRequired;
        BaseDto baseDto = new BaseDto();
        try {
            /** 0. 判断当前用户是否正常,如果不是,报错 **/
            User user = userService.getByPrimaryKeyWithoutComplete(userId);
            boolean active = userRoleService.checkMemberActive(userId);
            if (!active)
                return BaseDto.error("请先激活账号");
            if (user.getType() != UserType.MEMBER)
                return BaseDto.error("当前身份无法发布挂买单,请切换至会员身份");
            Integer state = userRoleService.getUserStateByUserIdAndUserType(userId, UserType.MEMBER);

            Boolean checkFeeCount = dealCommonService.checkFeeCount(userId, coinTypeId, DealScene.HANG_BUY, aliveCoinCount);
            if (!checkFeeCount) {
                BaseDto.error("请先充值交易钱包");
            }

            if (state != UserState.OK) {
                baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
                baseDto.setMsg("您已被封号或钱包已被冻结");
                return baseDto;
            }

            UserRealInfo userRealInfo = userRealInfoService.getByPrimaryKeyWithoutComplete(userId);
            if (userRealInfo == null || userRealInfo.getVerified() == 0) {
                return BaseDto.error("请先完成实名认证");
            } else {
                if (userRealInfo.getVerified() != 1) {
                    return BaseDto.error("请先完成实名认证");
                }
            }

            /** 1. 判断当前是否可以发布挂买单,如果不可以,报错 **/
            //Jedis //jedis = jedisUtil.getJedis();
            String able = jedisUtil.get(RedisKeyCreator.ablePublishHangBuy(userId));
            if (StringUtils.hasText(able)) {
                baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
                baseDto.setMsg("当前状态无法发布挂买单");
                //jedisUtil.close();
                return baseDto;
            }

            /** 2. 判断挂买单价是否符合规范,如果不符合,报错 **/
            /** 挂买单价 必须不低于 开盘价 的 最低挂买单价比例 **/

            /** 开盘价 **/
            BigDecimal openPrice = new BigDecimal(jedisUtil.get(RedisKeyCreator.openPrice(coinTypeId)));

            /** 最低挂买单价比例 **/
            String hangBuyOutPriceRatioStr = dealParamService.getValue(userId, coinTypeId, UserParamConst.HANG_BUY_OUT_PRICE_RATIO);
            BigDecimal minHangBuySinglePriceRate = new BigDecimal(hangBuyOutPriceRatioStr);

            /** 如果 singlePrice < openPrice * (minHangBuySinglePriceRate + 1) 就报错**/
            if (singlePrice.compareTo(openPrice.multiply((minHangBuySinglePriceRate).add(new BigDecimal(1)))) < 0) {
                //jedisUtil.close();
                baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
                baseDto.setMsg("挂买单价必须高于开盘价的" + minHangBuySinglePriceRate.toString());
                return baseDto;
            }
            //jedisUtil.close();

            /** 3. 判断当前现金余额是否够支付这笔挂买单,如果不够,报错 **/

            /** 当前买方钱包活币余额 **/
            BigDecimal cashCount = cashWalletService.getByPrimaryKey(userId).getCashCount();
            BigDecimal shouldPayAccount = singlePrice.multiply(aliveCoinCount);
            if (cashCount.compareTo(shouldPayAccount) < 0) {
                baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
                baseDto.setMsg("余额不足");
                return baseDto;
            }

            /** 4. 判断挂买后数量是否会超过交易钱包最大持有量 **/
            BigDecimal maxCount = new BigDecimal(jedisUtil.get(RedisKeyCreator.memberKeepAliveCoinMaxCount()));
            UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeIdAndUserType(userId, coinTypeId, UserType.MEMBER);
            BigDecimal nowAliveCoinCout = userCapital.getAliveCoinCount();
            if (nowAliveCoinCout.compareTo(maxCount.add(aliveCoinCount)) < 0) {
                baseDto.setCode(CodeConst.ERROR);
                baseDto.setMsg("将超过会员钱包最大持有量");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return BaseDto.error("位置错误");
        }
        return BaseDto.ok("success");
    }

    @RequestMapping("/deal/hangSale/publish/verify")
    public BaseDto verifyPublishHangSale(Integer userId, BigDecimal aliveCoinCount, BigDecimal singlePrice,
                                         Integer coinTypeId, Integer hangType) {
        BaseDto capitalPasswordRequired = frontCommenController.isCapitalPasswordRequired(userId);
        if (capitalPasswordRequired.isError())
            return capitalPasswordRequired;
        BaseDto baseDto = new BaseDto();
        try {
            /** 0. 判断当前用户是否正常,如果不是,报错 **/
            User user = userService.getByPrimaryKeyWithoutComplete(userId);
            boolean active = userRoleService.checkMemberActive(userId);
            if (!active)
                return BaseDto.error("请先激活账号");
            if (user.getType() != UserType.MEMBER)
                return BaseDto.error("当前身份无法发布挂卖单,请切换至会员身份");
            Boolean checkFeeCount = dealCommonService.checkFeeCount(userId, coinTypeId, DealScene.HANG_BUY, aliveCoinCount);
            if (!checkFeeCount) {
                BaseDto.error("请先充值交易钱包");
            }
            Integer state = userRoleService.getUserStateByUserIdAndUserType(userId, UserType.MEMBER);
            if (state != UserState.OK) {
                baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
                baseDto.setMsg("您已被封号或钱包已被冻结");
                return baseDto;
            }

            UserRealInfo userRealInfo = userRealInfoService.getByPrimaryKeyWithoutComplete(userId);
            if (userRealInfo == null || userRealInfo.getVerified() == 0) {
                return BaseDto.error("请先完成实名认证");
            } else {
                if (userRealInfo.getVerified() != 1) {
                    return BaseDto.error("请先完成实名认证");
                }
            }
            /** 1. 判断当前是否可以发布挂卖单,如果不可以,报错 **/
            //Jedis //jedis = jedisUtil.getJedis();
            String able = jedisUtil.get(RedisKeyCreator.ablePublishHangSale(userId));
            //jedisUtil.close();
            if (StringUtils.hasText(able)) {
                baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
                baseDto.setMsg("当前状态无法发布挂卖单");
                return baseDto;
            }

            /** 开盘价 **/
            BigDecimal openPrice = new BigDecimal(jedisUtil.get(RedisKeyCreator.openPrice(coinTypeId)));


            /**
             * 2. 查看当前挂卖量是否需要使用坐空权限,如果不要,继续
             * 3. 如果需要使用坐空,查看该用户当前剩余坐空次数,如果没有了,报错
             * 4. 如果坐空次数大于0, 将坐空次数减一并放入数据库中
             */
            /** 当前卖方钱包活币余额 **/
            BigDecimal saleUserAliveCoinBalance = userCapitalService.getByUserIdAndCoinTypeIdAndUserType(userId, coinTypeId, UserType.MEMBER).getAliveCoinCount();
            /** 挂卖量 必须不高于当前卖方钱包余额  **/

            /** 获取交易钱包最小活币量 **/
            String dealWalletMinCountStr = dealParamService.getValue(userId, coinTypeId, UserParamConst.MEMBER_KEEP_ALIVE_COIN_MIN_COUNT);
            BigDecimal dealWalletMinCount = new BigDecimal(dealWalletMinCountStr);

            /** 如果 卖方钱包余额 - 挂卖量 <  交易钱包最小活币量, 就查看坐空权限**/
            if ((saleUserAliveCoinBalance.subtract(aliveCoinCount)).compareTo(dealWalletMinCount) < 0) {
                Integer userShortCount = shortService.getUserShortCount(userId, coinTypeId);
                if (userShortCount == 0) {
                    baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
                    baseDto.setMsg("挂卖数量必须不高于" + (saleUserAliveCoinBalance.subtract(dealWalletMinCount)).toString());
                    return baseDto;
                } else if (userShortCount > 0) {
                    /** 使用坐空 **/
                    Integer userShortDeadline = shortService.getUserShortDeadline(userId, coinTypeId);
                    if (!shortService.insertShort(userId, coinTypeId, userShortCount - 1, userShortDeadline)) {
                        shortService.updateShort(userId, coinTypeId, userShortCount - 1, userShortDeadline);
                        Jedis jedis1 = jedisUtil.getJedis();
                        jedis1.set(RedisKeyCreator.shortStartTime(userId), LocalDateTime.now().toString());
                        jedis1.close();
                    }
                }
            }

            /** 回收挂卖 **/
            if (hangType == HangTypeConst.BUY_BACK_SALE) {
                if (singlePrice.compareTo(openPrice) > 0) {
                    return BaseDto.error("回收挂卖的价格不能高于开盘价");
                }
            } else if (hangType == HangTypeConst.LIMIT_PRICE_BUY) {
                /** 5. 如果是限价挂卖,则获取限价挂卖系数, 然后判断挂卖单价是否符合规范,不符合就报错 **/

                /** 限价挂卖系数 **/
                BigDecimal limitPriceSale = new BigDecimal(jedisUtil.get(RedisKeyCreator.limitPriceSale()));
                /** 如果 单价 小于 今日开盘价 * (1 + 限价挂卖系数) 就报错 **/
                BigDecimal min = openPrice.multiply(new BigDecimal(1).add(limitPriceSale));
                if (singlePrice.compareTo(min) < 0) {
                    baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
                    baseDto.setMsg("限价挂卖方式单价必须不低于" + min);
                    return baseDto;
                }
            }
            /** 挂卖量 必须 小于 余额, 否则报错**/
            if (aliveCoinCount.compareTo(saleUserAliveCoinBalance) > 0) {
                baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
                baseDto.setMsg(" 挂卖量 必须不高于" + saleUserAliveCoinBalance);
                return baseDto;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return BaseDto.error("未知错误");
        }
        return BaseDto.ok("success");
    }

    @RequestMapping("/deal/hangSale/buy/verify")
    public BaseDto verifyBuyHangSale(Integer buyUserId, Integer hangSaleId, BigDecimal count) {
        BaseDto capitalPasswordRequired = frontCommenController.isCapitalPasswordRequired(buyUserId);
        if (capitalPasswordRequired.isError())
            return capitalPasswordRequired;
        boolean b = userService.hasRole(buyUserId, UserType.MEMBER);
        if (!b)
            return BaseDto.error("你不是已激活会员,不能购买活币");
        Integer state = userRoleService.getUserStateByUserIdAndUserType(buyUserId, UserType.MEMBER);
        if (state != UserState.OK)
            return BaseDto.error("当前状态无法进行交易");

        HangSale hangSale = hangSaleService.getByPrimaryKey(hangSaleId);

        Boolean checkFeeCount = dealCommonService.checkFeeCount(buyUserId, hangSale.getCoinTypeId(), DealScene.HANG_BUY, count);
        if (!checkFeeCount) {
            BaseDto.error("请先充值交易钱包");
        }

        UserRealInfo userRealInfo = userRealInfoService.getByPrimaryKeyWithoutComplete(buyUserId);
        if (userRealInfo == null || userRealInfo.getVerified() == 0) {
            return BaseDto.error("请先完成实名认证");
        } else {
            if (userRealInfo.getVerified() != 1) {
                return BaseDto.error("请先完成实名认证");
            }
        }
        /** 如果要买的数量大于挂卖单余额,报错 **/
        if (hangSale.getSurplusCoinCount().compareTo(count) < 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
            baseDto.setMsg("该笔挂卖单余额不足");
            return baseDto;
        }

        /** 如果 要买的数量 + 用户活币余额 >  交易钱包活币最高持有量, 报错**/
        Integer coinTypeId = hangSale.getCoinTypeId();
        BigDecimal buyUserAliveCoinCount = userCapitalService.getByUserIdAndCoinTypeId(buyUserId, coinTypeId).getAliveCoinCount();
        BigDecimal dealWalletMaxCount = new BigDecimal(dealParamService.getValue(buyUserId, coinTypeId, UserParamConst.MEMBER_KEEP_ALIVE_COIN_MAX_COUNT));
        if (count.add(buyUserAliveCoinCount).compareTo(dealWalletMaxCount) > 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
            baseDto.setMsg("要买的数量超过了限制,交易钱包活币最高持有量为: " + dealWalletMaxCount);
            return baseDto;
        }

        /** 如果买方现金钱包不够支付,报错 **/
        BigDecimal cashCount = cashWalletService.getByPrimaryKey(buyUserId).getCashCount();
        BigDecimal shouldPayCashCount = count.multiply(hangSale.getSinglePrice());
        if (cashCount.compareTo(shouldPayCashCount) < 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
            baseDto.setMsg("现金余额不足");
            return baseDto;
        }
        return BaseDto.ok("success");
    }

    @RequestMapping("/deal/hangBuy/sale/verify")
    public BaseDto verifySaleHangBuy(Integer saleUserId, Integer hangBuyId, BigDecimal count) {
        BaseDto capitalPasswordRequired = frontCommenController.isCapitalPasswordRequired(saleUserId);
        if (capitalPasswordRequired.isError())
            return capitalPasswordRequired;
        boolean b = userService.hasRole(saleUserId, UserType.MEMBER);
        if (!b)
            return BaseDto.error("你不是已激活会员,不能卖出活币");
        Integer state = userRoleService.getUserStateByUserIdAndUserType(saleUserId, UserType.MEMBER);
        if (state != UserState.OK)
            return BaseDto.error("当前状态无法进行交易");
        HangBuy hangBuy = hangBuyService.getByPrimaryKey(hangBuyId);

        UserRealInfo userRealInfo = userRealInfoService.getByPrimaryKeyWithoutComplete(saleUserId);
        if (userRealInfo == null || userRealInfo.getVerified() == 0) {
            return BaseDto.error("请先完成实名认证");
        } else {
            if (userRealInfo.getVerified() != 1) {
                return BaseDto.error("请先完成实名认证");
            }
        }
        /** 如果要买的数量大于挂卖单余额,报错 **/
        if (hangBuy.getSurplusCoinCount().compareTo(count) < 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
            baseDto.setMsg("该比挂买单余额不足");
            return baseDto;
        }
        /**校验手续费够不够**/
        Boolean checkFeeCount = dealCommonService.checkFeeCount(saleUserId, hangBuy.getCoinTypeId(), DealScene.HANG_BUY, count);
        if (!checkFeeCount) {
            BaseDto.error("请先充值交易钱包");
        }
        Integer coinTypeId = hangBuy.getCoinTypeId();
//        BigDecimal buyUserAliveCoinCount = userCapitalService.getByUserIdAndCoinTypeId(buyUserId, coinTypeId).getAliveCoinCount();
//        BigDecimal dealWalletMaxCount = new BigDecimal(dealParamService.getValue(buyUserId, coinTypeId, UserParamConst.DEAL_WALLET_MAX_COUNT));
//        if (count.add(buyUserAliveCoinCount).compareTo(dealWalletMaxCount) > 0)
//        {
//            BaseDto baseDto = new BaseDto();
//            baseDto.setCode(CodeConst.ERROR);
//            baseDto.setMsg("要买的数量超过了限制,交易钱包活币最高持有量为: " + dealWalletMaxCount);
//            return baseDto;
//        }

        /** 如果卖方交易钱包余额不够支付,报错 **/
        BigDecimal aliveCoinCount = userCapitalService.getByUserIdAndCoinTypeId(saleUserId, coinTypeId).getAliveCoinCount();
        BigDecimal shouldPayCashCount = count;
        if (aliveCoinCount.compareTo(shouldPayCashCount) < 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(cn.net.shuxing.yifu.common.constant.CodeConst.ERROR);
            baseDto.setMsg("卖方活币余额不足");
            return baseDto;
        }
        return BaseDto.ok("success");
    }


    /**
     * 发布挂买单
     *
     * @param userId         发布者用户id
     * @param aliveCoinCount 挂买量
     * @param singlePrice    单价
     * @param coinTypeId     币种id
     * @param transferKey    交易key
     * @return
     */
    @ApiOperation(value = "发布挂买单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "发布者用户id", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "aliveCoinCount", value = "挂买量", required = true, dataType = "double", paramType = "query"),
            @ApiImplicitParam(name = "singlePrice", value = "单价", required = true, dataType = "double", paramType = "query"),
            @ApiImplicitParam(name = "coinTypeId", value = "币种id", required = true, dataType = "Integer", paramType = "query")
    })
    @RequestMapping(value = "/deal/hangBuy/publish")
    public BaseDto publishHangBuy(Integer userId, BigDecimal aliveCoinCount, BigDecimal singlePrice, Integer coinTypeId, String transferKey) {
        if (!frontCommonService.verifyTransferKey(userId, transferKey))
            return BaseDto.error("请先完成人脸识别和资金密码验证");
        BaseDto baseDto = hangBuyService.publishHangBuy(userId, aliveCoinCount, singlePrice, coinTypeId);
        return baseDto;
    }

    /**
     * 发布挂卖单
     *
     * @param userId         发布者用户id
     * @param aliveCoinCount 挂卖量
     * @param singlePrice    单价
     * @param coinTypeId     币种id
     * @param hangType       挂卖类型
     * @param transferKey    交易key
     * @return
     */
    @ApiOperation(value = "发布挂卖单", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "发布者用户id", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "aliveCoinCount", value = "挂卖量", required = true, dataType = "double", paramType = "query"),
            @ApiImplicitParam(name = "singlePrice", value = "单价", required = true, dataType = "double", paramType = "query"),
            @ApiImplicitParam(name = "coinTypeId", value = "币种id", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "hangType", value = "挂卖类型", required = true, dataType = "Integer", paramType = "query")
    })

    @RequestMapping(value = "/deal/hangSale/publish")
    public BaseDto publishHangSale(Integer userId, BigDecimal aliveCoinCount, BigDecimal singlePrice,
                                   Integer coinTypeId, Integer hangType,
                                   String transferKey) {
        if (!frontCommonService.verifyTransferKey(userId, transferKey))
            return BaseDto.error("请先完成人脸识别和资金密码验证");
        BaseDto baseDto = hangSaleService.publishHangSale(userId, aliveCoinCount, singlePrice, coinTypeId, hangType);
        return baseDto;
    }

    /**
     * 手动购买挂卖单
     *
     * @param buyUserId
     * @param hangSaleId
     * @param count
     * @param transferKey 交易key
     * @return
     */
    @ApiOperation(value = "手动购买挂卖单", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "buyUserId", value = "买方用户id", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "hangSaleId", value = "挂卖单id", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "count", value = "交易数量", required = true, dataType = "double", paramType = "query")
    })
    @RequestMapping("/deal/hangSale/buy")
    public BaseDto buyHangSale(Integer buyUserId, Integer hangSaleId, BigDecimal count, String transferKey) {
        if (!frontCommonService.verifyTransferKey(buyUserId, transferKey))
            return BaseDto.error("请先完成人脸识别和资金密码验证");
        return dealHistoryService.buyHangSale(buyUserId, hangSaleId, count);
    }

    /**
     * 手动卖给挂买单
     *
     * @param saleUserId
     * @param hangBuyId
     * @param count
     * @param transferKey 交易key
     * @return
     */
    @ApiOperation(value = "手动卖给挂买单", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "saleUserId", value = "卖方用户id", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "hangBuyId", value = "挂买单id", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "count", value = "交易数量", required = true, dataType = "double", paramType = "query")
    })

    @RequestMapping("/deal/hangBuy/sale")
    public BaseDto saleHangBuy(Integer saleUserId, Integer hangBuyId, BigDecimal count, String transferKey) {
        if (!frontCommonService.verifyTransferKey(saleUserId, transferKey))
            return BaseDto.error("请先完成人脸识别和资金密码验证");
        return dealHistoryService.saleHangBuy(saleUserId, hangBuyId, count);
    }

    @ApiOperation(value = "查询我的所有在线交易", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, dataType = "Integer", paramType = "query"),
    })

    @RequestMapping("/deal/online/mine/all")
    @ResponseBody
    public BaseDto getMyOnlineDeal(Integer userId) {
        BaseDto baseDto1 = checkUserId(userId);
        if (baseDto1 != null) {
            return baseDto1;
        }
        HangBuy hangBuy = hangBuyService.getDealingByUserId(userId);
        HangSale hangSale = hangSaleService.getDealingByUserId(userId);
        List<Object> list = new ArrayList<>();
        if (hangBuy != null)
            list.add(hangBuy);
        if (hangSale != null)
            list.add(hangSale);
        return BaseDto.ok(list);

    }

    /**
     * 查看交易明细
     *
     * @param userId     用户id
     * @param coinTypeId 币种id
     * @param startDate  起始时间,格式yyyy-MM-dd
     * @param endDate    结束时间,格式yyyy-MM-dd
     * @param pageNum    页数,默认为1
     * @param pageSize   本页显示条数,默认为10
     * @return
     */
    @RequestMapping("/deal/detail/mine")
    public BaseDto getDealDetail(Integer userId,
                                 Integer coinTypeId,
                                 String startDate,
                                 String endDate,
                                 @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                 @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        System.out.println("userId是" + userId);
        BaseDto baseDto = new BaseDto();
        LocalDate now = LocalDate.now();
        LocalDate startLocaltDate = null;
        LocalDate endLocalDate = null;
        if (StringUtils.hasText(startDate)) {
            startLocaltDate = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } else {
            startLocaltDate = now.minusYears(20);
        }

        if (StringUtils.hasText(endDate)) {
            endLocalDate = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } else {
            endLocalDate = now;
        }
        endLocalDate = endLocalDate.plusDays(1);

        List<UserDealHistory> userDealHistoryList = userDealHistoryService.getHangBuyAndHangSaleAndSystemBuyBackByUserIdAndDate(userId, startLocaltDate, endLocalDate, pageNum, pageSize);

        baseDto.setData(userDealHistoryList);
        baseDto.setCode(0);
        return baseDto;
    }

    @RequestMapping("/deal/detail/mineClassify")
    public BaseDto getDealDetailClassify(Integer userId,
                                         String startDate,
                                         String endDate,
                                         @RequestParam(value = "dealType", defaultValue = "-1") Integer dealType,
                                         @RequestParam(value = "dealScene", defaultValue = "-1") Integer dealScene,
                                         @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                         @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        BaseDto baseDto = new BaseDto();
        LocalDate now = LocalDate.now();
        LocalDate startLocaltDate = null;
        LocalDate endLocalDate = null;
        boolean b = userService.checkUser(userId);

        if (StringUtils.hasText(startDate)) {
            startLocaltDate = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } else {
            startLocaltDate = now.minusYears(20);
        }

        if (StringUtils.hasText(endDate)) {
            endLocalDate = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } else {
            endLocalDate = now;
        }
        endLocalDate = endLocalDate.plusDays(1);

        if (dealType == (-1)) {
            List<DealRecordDto> dealRecordDtos = userDealHistoryService.getsByDateAndDealScene(userId, dealScene, startLocaltDate, endLocalDate, pageNum, pageSize);
            baseDto.setData(dealRecordDtos);
            baseDto.setCode(0);
        }
        if (dealScene == (-1)) {
            if (dealType > 9 && dealType != 28) {
                List<DealRecordDto> dealRecordDtos = userCashHistoryService.getsByUserIdAndDealType(userId, dealType, pageNum, pageSize);
                baseDto.setData(dealRecordDtos);
                baseDto.setCode(0);
            } else if (dealType < 9) {
                List<DealRecordDto> dealRecordDtos = userDealHistoryService.getsByDateAndDealTypeAndUserId(userId, dealType, startLocaltDate, endLocalDate, pageNum, pageSize);
                baseDto.setData(dealRecordDtos);
                baseDto.setCode(0);
            }

        }
        if (dealType == 5) {
            List<DealRecordDto> dealRecordDtos = userDealHistoryService.getsByDateAndDealTypeIsFee(userId, dealType, startLocaltDate, endLocalDate, pageNum, pageSize);
            baseDto.setData(dealRecordDtos);
            baseDto.setCode(0);
        }
        if (dealType == 8) {
            List<DealRecordDto> dealRecordDtos = userDealHistoryService.getAllHistory(userId, dealType, startLocaltDate, endLocalDate, pageNum, pageSize);
            baseDto.setData(dealRecordDtos);
            baseDto.setCode(0);
        }
        if (dealType == 28) {
            List<DealRecordDto> dealRecordDtos = userCashHistoryService.getsCashByUserId(userId, pageNum, pageSize);
            baseDto.setData(dealRecordDtos);
            baseDto.setCode(0);
        }
        return baseDto;
    }

    /**
     * 查看cash记录
     *
     * @param userId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @RequestMapping("/cash/detail/mine")
    public BaseDto getCashDetail(Integer userId,
                                 Integer pageNum,
                                 Integer pageSize) {
        List<UserCashHistory> userCashHistories = userCashHistoryService.getsByUserIdAndUserType(userId, pageNum, pageSize);
        return BaseDto.ok(userCashHistories);
    }

    /**
     * 查看转账明细
     *
     * @param userId     用户id
     * @param coinTypeId 币种id
     * @param startDate  起始时间,格式yyyy-MM-dd
     * @param endDate    结束时间,格式yyyy-MM-dd
     * @param pageNum    页数,默认为1
     * @param pageSize   本页显示条数,默认为10
     * @return
     */
    @RequestMapping("/transfer/detail/mine")
    public BaseDto getTransferDetail(Integer userId,
                                     Integer coinTypeId,
                                     String startDate,
                                     String endDate,
                                     @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                     @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        BaseDto baseDto = new BaseDto();
        LocalDate now = LocalDate.now();
        LocalDate startLocaltDate = null;
        LocalDate endLocalDate = null;
        if (StringUtils.hasText(startDate)) {
            startLocaltDate = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } else {
            startLocaltDate = now.minusYears(20);
        }

        if (StringUtils.hasText(endDate)) {
            endLocalDate = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } else {
            endLocalDate = now;
        }
        endLocalDate = endLocalDate.plusDays(1);

        List<UserDealHistory> userDealHistoryList = userDealHistoryService.getTransfersByUserIdAndCoinTypeIdAndDate(userId, coinTypeId, startLocaltDate, endLocalDate, pageNum, pageSize);

        baseDto.setData(userDealHistoryList);
        baseDto.setCode(0);
        return baseDto;
    }


    @ApiOperation(value = "修改交易单价或交易总量", httpMethod = "PUT")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "dealType", value = "交易类型", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "price", value = "交易单价", required = true, dataType = "double", paramType = "query"),
            @ApiImplicitParam(name = "count", value = "交易总量", required = true, dataType = "double", paramType = "query")
    })
    @RequestMapping("/deal/update")
    public BaseDto update(Integer userId, Integer dealType, BigDecimal price, String transferKey) {
        if (!frontCommonService.verifyTransferKey(userId, transferKey))
            return BaseDto.error("请先完成人脸识别和资金密码验证");
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null)
            return baseDto;

        BaseDto myOnlineDealBaseDto = getMyOnlineDeal(userId, dealType);
        if (myOnlineDealBaseDto.getCode() == CodeConst.ERROR)
            return myOnlineDealBaseDto;
        else {
            if (dealType == DealType.HANG_BUY) {
                HangBuy hangBuy = (HangBuy) myOnlineDealBaseDto.getData();
                boolean flag = false;
                BigDecimal count = hangBuy.getSurplusCoinCount();
                BigDecimal oldOrderValue = count.multiply(hangBuy.getSinglePrice());
                BigDecimal newOrderValue = price.multiply(count);
                BigDecimal dealCash = newOrderValue.subtract(oldOrderValue);
                Boolean checkValue = false;

                if (newOrderValue.compareTo(oldOrderValue) > 0) {
                    checkValue = true;
                    CashWallet cashWallet = cashWalletService.getByUserId(userId);
                    BigDecimal cashCount = cashWallet.getCashCount();
                    if (dealCash.compareTo(cashCount) > 0) {
                        myOnlineDealBaseDto.setCode(CodeConst.ERROR);
                        myOnlineDealBaseDto.setMsg("现金钱包余额不足,无法修改订单");
                        return myOnlineDealBaseDto;
                    }
                }

                if (checkValue) {
                    memberWalletService.reduceCash(userId, dealCash, CashChangeType.CASH_HANG_BUY, hangBuy.getOrderKey());
                }

                if (price != null) {
                    hangBuy.setSinglePrice(price);
                    flag = true;
                }

                if (flag) {
                    hangBuyService.update(hangBuy);
                }
                return getMyOnlineDeal(userId, dealType);
            }

            if (dealType == DealType.HANG_SALE) {
                HangSale hangSale = (HangSale) myOnlineDealBaseDto.getData();
                boolean flag = false;
                if (price != null) {
                    hangSale.setSinglePrice(price);
                    flag = true;
                }
                if (flag) {
                    hangSaleService.update(hangSale);
                }
                return getMyOnlineDeal(userId, dealType);
            }
        }
        return myOnlineDealBaseDto;
    }


    @ApiOperation(value = "撤单", httpMethod = "PUT")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "dealType", value = "交易类型", required = true, dataType = "Integer", paramType = "query")
    })
    @RequestMapping("/deal/cancel")
    public BaseDto cancel(Integer userId, Integer dealType) {
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null)
            return baseDto;

        BaseDto myOnlineDealBaseDto = getMyOnlineDeal(userId, dealType);
        if (myOnlineDealBaseDto.getCode() == CodeConst.ERROR)
            return myOnlineDealBaseDto;
        if (myOnlineDealBaseDto.getData() == null) {
            BaseDto totalBase = new BaseDto();
            totalBase.setCode(CodeConst.ERROR);
            totalBase.setMsg("当前无在线交易单,无法撤单");
            return totalBase;
        } else {
            if (dealType == DealType.HANG_BUY) {
                HangBuy hangBuy = (HangBuy) myOnlineDealBaseDto.getData();
                hangBuyService.cancel(hangBuy.getId());
                BaseDto baseDto1 = new BaseDto();
                baseDto1.setData("撤单成功");
                return baseDto1;
            }
            if (dealType == DealType.HANG_SALE) {
                BaseDto baseDto2 = new BaseDto();
                HangSale hangSale = (HangSale) myOnlineDealBaseDto.getData();
                hangSaleService.cancel(hangSale.getId());
                /** 4. 判断挂买后数量是否会超过交易钱包最大持有量 **/
                BigDecimal maxCount = new BigDecimal(jedisUtil.get(RedisKeyCreator.memberKeepAliveCoinMaxCount()));
                UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeIdAndUserType(userId, hangSale.getCoinTypeId(), UserType.MEMBER);
                BigDecimal nowAliveCoinCout = userCapital.getAliveCoinCount();
                if (nowAliveCoinCout.compareTo(maxCount.add(hangSale.getSurplusCoinCount())) > 0) {
                    baseDto2.setCode(CodeConst.ERROR);
                    baseDto2.setMsg("数量超过交易钱包最大持有量,当前不能撤销");
                    return baseDto2;
                } else {
                    baseDto2.setData("撤单成功");
                    return baseDto2;
                }
            }
        }
        return myOnlineDealBaseDto;
    }


    @ApiOperation(value = "获取全站成交记录", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "分页显示的页数", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "分页显示本页显示数据的条数", required = true, dataType = "Integer", paramType = "query")
    })
    @RequestMapping("/deal/whole/newest")
    public BaseDto getWholeSiteDealHistory(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                           @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        List<DealHistory> dealHistoryList = dealHistoryService.getAllNewestWithoutComplete(pageNum, pageSize);
        BaseDto baseDto = new BaseDto();
        baseDto.setData(dealHistoryList);
        return baseDto;
    }

    @ApiOperation(value = "获取我的成交记录", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "发布者用户id", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "分页显示的页数", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "分页显示本页显示数据的条数", required = true, dataType = "Integer", paramType = "query")
    })
    @RequestMapping("/deal/mine/newest")
    public BaseDto getMySiteDealHistory(Integer userId,
                                        @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                        @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null)
            return baseDto;
        List<UserDealHistory> userDealHistoryList = userDealHistoryService.getHangBuyAndHangSaleAndSystemBuyBackByUserId(userId, pageNum, pageSize);
        BaseDto baseDto1 = new BaseDto();
        baseDto1.setData(userDealHistoryList);
        return baseDto1;
    }


    /**
     * 获取挂买单排行
     *
     * @return
     */
    @RequestMapping("/deal/hangBuy/rank")
    public BaseDto getHangBuyRank(Integer coinTypeId) {
        List<HangBuy> hangBuyList = hangBuyService.getHangBuyRank(coinTypeId, 50);
        return BaseDto.ok(hangBuyList);
    }

    /**
     * 获取挂卖单排行
     *
     * @return
     */
    @RequestMapping("/deal/hangSale/rank")
    public BaseDto getHangSaleRank(Integer coinTypeId) {
        List<HangSale> hangSaleRank = hangSaleService.getHangSaleRank(coinTypeId, 50);
        return BaseDto.ok(hangSaleRank);
    }

    @RequestMapping("/deal/coinType/all")
    public BaseDto getAllCoinType() {
        List<CoinType> all = coinTypeService.getAll();
        return BaseDto.ok(all);
    }

    /**
     * 搜索币种
     *
     * @param name
     * @return
     */
    @RequestMapping("/deal/coinType/search")
    public BaseDto searchCoinTypeByName(String name) throws UnsupportedEncodingException {
//        System.out.println("解析前coinTypeName"+name);
        String newName = new String(name.getBytes("ISO-8859-1"), "UTF-8");
//        System.out.println("解析后coinTypeName"+newName);
        BaseDto baseDto = new BaseDto();
        ArrayList<CoinType> newCoinTypeList = new ArrayList<>();
        List<CoinType> coinTypes = coinTypeService.searchByName(newName);
        for (CoinType coinType : coinTypes) {
            BigDecimal coinGain = coinRatioService.calculateCoinGain(coinType.getId());
            coinType.setCoinGain(coinGain.subtract(new BigDecimal(1)).multiply(new BigDecimal(100)));
            coinType.setNewestPrice(openPriceHistoryService.getOpenPrice(coinType.getId()));
            newCoinTypeList.add(coinType);
        }
        baseDto.setData(newCoinTypeList);
        baseDto.setCode(0);
        return baseDto;
    }

    /**
     * 获取回购服务费率
     *
     * @param userId
     * @param coinTypeId
     * @return
     */
    @RequestMapping("/deal/fee/service")
    public BaseDto getServiceFee(Integer userId, Integer coinTypeId) {
        String value = dealParamService.getValue(userId, coinTypeId, UserParamConst.BUY_BACK_SERVICE_FEE);
        return BaseDto.ok(value);
    }

    /**
     * 获取最大可转账金额
     *
     * @param userId     用户id
     * @param coinTypeId 币种id
     * @return
     */
    @RequestMapping("/deal/transfer/maxCount")
    public BaseDto getTransferMaxCount(Integer userId, Integer coinTypeId) {
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null && baseDto.isError())
            return baseDto;
        UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeId(userId, coinTypeId);
        Integer type = userService.getByPrimaryKey(userId).getType();
        if (type == UserType.SHAREHOLDER) {
            return BaseDto.ok(userCapital.getAliveCoinCount());
        }
        Integer userShortCount = shortService.getUserShortCount(userId, coinTypeId);
        if (userShortCount > 0) {
            return BaseDto.ok(userCapital.getAliveCoinCount());
        } else {
            String value = dealParamService.getValue(userId, coinTypeId, UserParamConst.MEMBER_KEEP_ALIVE_COIN_MIN_COUNT);
            BigDecimal dealWalletMinCount = new BigDecimal(value);
            return BaseDto.ok(userCapital.getAliveCoinCount().subtract(dealWalletMinCount));
        }
    }

    /**
     * 获取已完成的订单
     *
     * @param userId
     * @param coinTypeId
     * @param dealType
     * @return
     */
    @RequestMapping("/deal/completed/mine")
    public BaseDto getMyCompletedDeal(Integer userId, Integer coinTypeId, Integer dealType,
                                      @RequestParam(defaultValue = "1", value = "pageNum") int pageNum,
                                      @RequestParam(defaultValue = "10", value = "pageSize") int pageSize) {
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null && baseDto.isError())
            return baseDto;

        List<BaseBean> list = new ArrayList<>();
        if (dealType == DealType.HANG_BUY) {
            List<HangBuy> completedHangBuy = hangBuyService.getCompletedHangBuy(userId, coinTypeId, pageNum, pageSize);
            list.addAll(completedHangBuy);
        }
        if (dealType == DealType.HANG_SALE) {
            List<HangSale> completedHangSale = hangSaleService.getCompletedHangSale(userId, coinTypeId, pageNum, pageSize);
            list.addAll(completedHangSale);
        }
        list.sort((x, y) -> {
            return y.getCreateTime().compareTo(x.getCreateTime());
        });

        return BaseDto.ok(list);
    }


    /**
     * 获取我的在线交易(根据交易类型)
     *
     * @param userId   用户id
     * @param dealType 交易类型
     * @return
     */
    @RequestMapping("/deal/online/mine")
    @ResponseBody
    public BaseDto getMyOnlineDeal(Integer userId, int dealType) {
        BaseDto baseDto1 = checkUserId(userId);
        if (baseDto1 != null) {
            return baseDto1;
        }

        if (dealType == DealType.HANG_BUY) {
            HangBuy hangBuy = hangBuyService.getDealingByUserId(userId);
            return BaseDto.ok(hangBuy);
        }

        if (dealType == DealType.HANG_SALE) {
            HangSale hangSale = hangSaleService.getDealingByUserId(userId);
            return BaseDto.ok(hangSale);
        }

        return BaseDto.error("dealType参数只能为0(挂买)或1(挂卖)");
    }

    /**
     * 获取已撤单的订单
     *
     * @param userId
     * @param coinTypeId
     * @return
     */
    @RequestMapping("/deal/cancel/mine")
    public BaseDto getMyCancelDeal(Integer userId, Integer coinTypeId, Integer dealType,
                                   @RequestParam(defaultValue = "1", value = "pageNum") int pageNum,
                                   @RequestParam(defaultValue = "10", value = "pageSize") int pageSize) {
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null && baseDto.isError())
            return baseDto;

        List<BaseBean> list = new ArrayList<>();
        if (dealType == DealType.HANG_BUY) {
            List<HangBuy> completedHangBuy = hangBuyService.getCancelHangBuy(userId, coinTypeId, pageNum, pageSize);
            list.addAll(completedHangBuy);
        }
        if (dealType == DealType.HANG_SALE) {
            List<HangSale> completedHangSale = hangSaleService.getCancelHangSale(userId, coinTypeId, pageNum, pageSize);
            list.addAll(completedHangSale);
        }
//        list.sort((x, y) -> {
//            return y.getCreateTime().compareTo(x.getCreateTime());
//        });
        return BaseDto.ok(list);
    }

    /**
     * 获取所有的订单
     *
     * @param userId
     * @param coinTypeId
     * @return
     */
    @RequestMapping("/deal/all/mine")
    public BaseDto getMyAllDeal(Integer userId, Integer coinTypeId, Integer dealType,
                                @RequestParam(defaultValue = "1", value = "pageNum") int pageNum,
                                @RequestParam(defaultValue = "10", value = "pageSize") int pageSize) {
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null && baseDto.isError())
            return baseDto;

        List<BaseBean> list = new ArrayList<>();
        if (dealType == DealType.HANG_BUY) {
            List<HangBuy> completedHangBuy = hangBuyService.getTotalByUserIdAndCoinType(userId, coinTypeId, pageNum, pageSize);
            list.addAll(completedHangBuy);
        }
        if (dealType == DealType.HANG_SALE) {
            List<HangSale> completedHangSale = hangSaleService.getTotalByUserIdAndCoinType(userId, coinTypeId, pageNum, pageSize);
            list.addAll(completedHangSale);
        }
        baseDto = new BaseDto();
        baseDto.setData(list);
        baseDto.setCode(CodeConst.OK);
        return baseDto;
    }

    /**
     * 获取累计交易订单量和今日交易订单量
     *
     * @return
     */
    @RequestMapping("/deal/count/mine")
    public BaseDto getDealOrderCount(Integer userId, Integer coinTypeId) {
        Map<String, Map<String, Object>> map = new HashMap<>();
        int totalCount = hangBuyService.getTotalByUserIdAndCoinType(userId, coinTypeId).size();
        int todayCount = hangBuyService.getTodayByUserIdAndCoinTypeId(userId, coinTypeId).size();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("totalCount", totalCount);
        map1.put("todayCount", todayCount);
        map.put("hangBuy", map1);

        totalCount = hangSaleService.getTotalByUserIdAndCoinType(userId, coinTypeId).size();
        todayCount = hangSaleService.getTodayByUserIdAndCoinTypeId(userId, coinTypeId).size();
        map1 = new HashMap<>();
        map1.put("totalCount", totalCount);
        map1.put("todayCount", todayCount);
        map.put("hangSale", map1);
        return BaseDto.ok(map);

        /*
        {
            hangBuy:{
                totalCount: 总发布单量,
                todayCount: 今日发布单量
            },
             hangSale:{
                totalCount: 总发布单量,
                todayCount: 今日发布单量
            }
        }
         */
    }

    /**
     * 获取累计交易量和本月交易量
     *
     * @param userId
     * @param coinTypeId
     * @return
     */
    @RequestMapping("/deal/mine/dealCount")
    public BaseDto getDealCount(Integer userId, Integer coinTypeId) {
        Map<String, String> map = new HashMap<>();
        BigDecimal totalDealCount = userDealHistoryService.getTotalByUserIdAndCoinTypeId(userId, coinTypeId);
        map.put("totalCount", totalDealCount.toString());

        BigDecimal thisMonthDealtCount = userDealHistoryService.getThisMonthByUserIdAndCoinTypeId(userId, coinTypeId);
        map.put("thisMonthCount", thisMonthDealtCount.toString());
        return BaseDto.ok(map);
        /*
        {
            totalCount: 累计交易量,
            thisMonthCount: 本月交易量
        }
         */
    }

    @RequestMapping("/deal/mine/mine")
    public BaseDto getMineCount(Integer userId) {
        Map<String, String> map = new HashMap<>();
        BigDecimal totalAliveCoinDividends = new BigDecimal(0);
        BigDecimal todayAliveCoinDividends = new BigDecimal(0);
        List<CoinType> all = coinTypeService.getAll();
        if (all!=null&&!all.isEmpty()){
            for (CoinType coinType : all) {
                Integer coinTypeId = coinType.getId();
                BigDecimal totalHaveDivdends = shareholderBuyGrantHistoryService.getTotalHaveDivdends(coinTypeId);
                totalAliveCoinDividends = totalAliveCoinDividends.add(totalHaveDivdends);
                List<ShareholderCoinGrantHistory> todaySysList = shareholderCoinGrantHistoryService.getTodayByCoinTypeIdAndType(coinTypeId, Type.ALIVECOIN);
                List<ShareholderBuyGrantHistory> todayBuyAliveList = shareholderBuyGrantHistoryService.getTodayByCoinTypeIdAndType(coinTypeId, Type.ALIVECOIN);
                if (todaySysList == null || todaySysList.isEmpty()) {
                    todayAliveCoinDividends = new BigDecimal(0);
                    for (ShareholderBuyGrantHistory shareholderBuyGrantHistory : todayBuyAliveList) {
                        BigDecimal count = shareholderBuyGrantHistory.getCount();
                        todayAliveCoinDividends = todayAliveCoinDividends.add(count);
                    }
                } else {
                    BigDecimal todayHaveDivdends = shareholderBuyGrantHistoryService.getTodayHaveDivdends(coinTypeId);
                    todayAliveCoinDividends = todayAliveCoinDividends.add(todayHaveDivdends);
                }
            }
        }

        map.put("totalCount",totalAliveCoinDividends.toString());
        map.put("todayCount", todayAliveCoinDividends.toString());
        return BaseDto.ok(map);
    }

    /**
     * 获取累计转账量和本月转账量
     *
     * @param userId
     * @param coinTypeId
     * @return
     */
    @RequestMapping("deal/mine/transferCount")
    public BaseDto getTransferCount(Integer userId, Integer coinTypeId) {
        Map<String, String> map = new HashMap<>();
        BigDecimal totalTransferCount = userDealHistoryService.getTotalTransferCount(userId, coinTypeId);
        if (totalTransferCount == null) {
            totalTransferCount = new BigDecimal(0);
        }
        map.put("totalCount", totalTransferCount.toString());

        BigDecimal thisMonthTransferCount = userDealHistoryService.getThisMonthTransferCount(userId, coinTypeId);
        if (thisMonthTransferCount == null) {
            thisMonthTransferCount = new BigDecimal(0);
        }
        map.put("thisMonthCount", thisMonthTransferCount.toString());
        return BaseDto.ok(map);

         /*
        {
            totalCount: 累计转账量,
            thisMonthCount: 本月转账量
        }
         */
    }

    /**
     * 可用现金余额
     *
     * @return
     */
    @RequestMapping("/deal/usable/cash")
    public BaseDto getUserableCashCount(int userId) {
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null && baseDto.isError())
            return baseDto;
        CashWallet cashWallet = cashWalletService.getByPrimaryKey(userId);
        BigDecimal count = new BigDecimal(0);
        if (cashWallet != null)
            count = cashWallet.getCashCount();
        return BaseDto.ok(count);
    }

    @RequestMapping("/deal/usable/cashToCNY")
    public BaseDto getUserableCashCountToCNY(int userId) {
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null && baseDto.isError())
            return baseDto;
        CashWallet cashWallet = cashWalletService.getByPrimaryKey(userId);
        BigDecimal count = new BigDecimal(0);
        if (cashWallet != null) {
            count = cashWallet.getCashCount();
            BigDecimal ethExchangeRate = new BigDecimal(jedisUtil.get(RedisKeyCreator.ethExchangeRate()));
            count = count.divide(ethExchangeRate, 8, BigDecimal.ROUND_HALF_UP);
        }
        return BaseDto.ok(count);
    }

    /**
     * 可用虚拟币余额
     *
     * @param userId     用户id
     * @param coinTypeId 币种id
     * @return
     */
    @RequestMapping("/deal/usable/coin")
    public BaseDto getUserableCoinCount(int userId, int coinTypeId) {
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null && baseDto.isError())
            return baseDto;
        User user = userService.getByPrimaryKeyWithoutComplete(userId);
        if (user.getType() == UserType.SHAREHOLDER) {
            UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeId(userId, coinTypeId);
            if (userCapital == null)
                return BaseDto.ok(new BigDecimal(0));
            return BaseDto.ok(userCapital.getAliveCoinCount());
        }
        Integer userShortCount = shortService.getUserShortCount(userId, coinTypeId);
        UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeId(userId, coinTypeId);
        if (userCapital == null)
            return BaseDto.ok(new BigDecimal(0));
        Integer state = userService.getByPrimaryKeyWithoutComplete(userId).getState();
        if (state != UserState.OK)
            return BaseDto.ok(new BigDecimal(0));
        if (userShortCount > 0) {
            return BaseDto.ok(userCapital.getAliveCoinCount().subtract(new BigDecimal(dealParamService.getValue(userId, coinTypeId, UserParamConst.MEMBER_KEEP_ALIVE_COIN_MIN_COUNT))));
        } else {
            String value = dealParamService.getValue(userId, coinTypeId, UserParamConst.MEMBER_KEEP_ALIVE_COIN_MIN_COUNT);
            return BaseDto.ok(userCapital.getAliveCoinCount().subtract(new BigDecimal(value)));
        }
    }

    @RequestMapping("/baseCount/recharge")
    public BaseDto getRechargeBaseCount() {
        //Jedis //jedis = jedisUtil.getJedis();
        String s = jedisUtil.get(RedisKeyCreator.rechargeBaseCount());
        //jedisUtil.close();
        if (!StringUtils.hasText(s))
            s = "0";
        return BaseDto.ok(s);
    }

    @RequestMapping("/baseCount/withdraw")
    public BaseDto getWithdrawBaseCount() {
        //Jedis //jedis = jedisUtil.getJedis();
        String s = jedisUtil.get(RedisKeyCreator.withdrawBaseCount());
        //jedisUtil.close();
        if (!StringUtils.hasText(s))
            s = "0";
        return BaseDto.ok(s);
    }

    /**
     * 行情
     *
     * @return
     */
    @RequestMapping("/deal/quotation")
    public BaseDto getQuotation() {
        List<CoinType> all = coinTypeService.getAll();
        List<Object> list = new ArrayList<>();

        for (CoinType coinType : all) {
            Map<String, Object> map = new HashMap<>();
            map.put("simpleName", coinType.getSimpleName());
            map.put("name", coinType.getName());
            map.put("newestPrice", coinType.getNewestPrice());
            map.put("gain", coinType.getCoinGain().subtract(new BigDecimal(1)).multiply(new BigDecimal(100)));
            CoinCompletedInfo coinCompletedInfo = coinCommonService.createCoinCompletedInfo(coinType.getId());

            map.put("dealCount", coinCompletedInfo.getTotalDealCount());
            map.put("releaseCount", coinCompletedInfo.getReleaseCount());
            list.add(map);
        }
        return BaseDto.ok(list);

        /*
           {
                simpleName: 货币简称
                newestPrice: 最新价
                gain: 涨幅
                dealCount: 交易量
                releaseCount: 释放量
           }
         */

    }

    @RequestMapping("/deal/mine/all")
    public BaseDto getMyAllDealOrder(Integer userId,
                                     Integer dealType,
                                     @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                     @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        BaseDto baseDto = checkUserId(userId);
        if (baseDto != null && baseDto.isError())
            return baseDto;


        if (dealType == DealType.HANG_SALE) {
            List<HangSale> hangSaleList = hangSaleService.getTotalByUserIdWithoutComplete(userId, pageNum, pageSize);
            return BaseDto.ok(hangSaleList);
        }
        if (dealType == DealType.HANG_BUY) {
            List<HangBuy> hangBuyList = hangBuyService.getTotalByUserIdWithoutComplete(userId, pageNum, pageSize);
            return BaseDto.ok(hangBuyList);
        }
        return BaseDto.error("只支持查询挂买(0)和挂卖(1)");
    }


//    @RequestMapping("/deal/checkDealCount")
//    public BaseDto checkDealCount(Integer userId,
//                                  Integer coinTypeId,
//                                  Integer dealType,
//                                  Integer dealScene,
//                                  BigDecimal dealCount) {
//        //1.判断cashWallet
//        //2.判断userCapital
//        BaseDto baseDto = new BaseDto();
//        User user = userService.getByPrimaryKey(userId);
//        UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeIdAndUserType(userId, coinTypeId, user.getType());
//        CashWallet cashWallet = cashWalletService.getByUserId(userId);
//        if (dealType == DealType.HANG_BUY) {
//
//        }
//        return baseDto;
//    }

//    @RequestMapping("/coin")
}
